// ManagedAPI.h

#pragma once

#pragma unmanaged
#include "src\udb.h"

#pragma managed
#include "Kind.h"
#include "Comments.h"
#include "Reference.h"
#include "UdbEnumWrappers.h"

using namespace System;
using namespace System::Collections::Generic;

namespace ManagedAPI
{
	public ref class Entity
	{
	public:
		static Entity^ Create(const UdbEntity&);
		// Clears out the static Entity dictionary sEntList. 
		// It is only called by the Database when it's closed down. No one else should call this.
		static void    Clear();
		~Entity();
	protected:
		Entity(const UdbEntity&);
	private:
		Entity();
	public:
		// Properties -------------------------
		property String^ NameShort  { String^ get(); }
		property String^ NameSimple { String^ get(); }
		property String^ NameLong   {	String^ get(); }
		property String^ NameUnique {	String^ get(); }
		property int     ID         {	int get();     }
		property Kind^   Kind	 { ManagedAPI::Kind^ get(); }
		property String^ KindName {	String^ get();	}
		// Returns the raw type of this object. This includes all modifier's in the type declaration.
		property String^ TypeText { String^ get();   }
		property int LineDefineStart    { int get(); }
		property int LineDefineEnd      { int get(); }
		property int LineDeclareStart    { int get(); }
		// Comments for this entity
		property ManagedAPI::Comments^ Comments { ManagedAPI::Comments^ get(); }
		
		// Methods -----------------------------
		virtual String^ ToString() override;
		
		// Returns the type of this entity as a string, with all the modifier keywords removed.
		// This simply parses and cleans up the string returned by the property Entity::TypeText.
		String^		 GetCleanType();
		// Returns the Entity that defines the type of this object.
		Entity^		 GetTypeEntity();
		// Returns the Reference that is this object.
		Reference^	 GetRef();
		/* Returns a list of references for the specified entity. 
		This takes (optionally) a string of the allowable entity kinds to 
		return and a string of the allowable reference kinds to use. */
		array<Reference^>^ Refs(String^ refKinds, String^ entKinds );

	protected:
		UdbEntity GetUdbEntity();
#ifdef CACHING_POINTERS_BUG
		UdbEntity mEntity; // only used in one place
#endif		
	private:
		String^ mNameShort;
		String^ mNameSimple;
		String^ mNameLong;
		String^ mUniqueName;
		int     mId;
		ManagedAPI::Kind^ mThisKind;
		String^ mType;
		Reference^ mReference;
		
		void InitializeBoundsaries(const UdbEntity);
		int mLineDefineStart;
		int mLineDefineEnd;
		int mLineDeclareStart;

		ManagedAPI::Comments^ mComments;
		
		// Static list of all Entities that are created. This removes the duplicate instantiation
		// of identical entities when old Entities are reused and referenced multiple times.
		static Dictionary<String^, Entity^>^ sEntList = gcnew Dictionary<String^, Entity^>();
	};
}
